package customers;
import java.util.Scanner;
import java.util.InputMismatchException;
import java.sql.*;

import database.DatabaseManager;

import reservations.Reservation;
import seats.Seat;

public class Customer 
{
	private String custName;				// customer first name
	private String custLastName;			// customer last name
	private String custAddress;				// customer address
	private String custId;					// customer id
	private String custTelphoneNum;			// customer telephone number
	private String userName;				// customer user name
	private String password;				// customer password
	private Reservation[] custReservation;		// to hold customer reservation
	private String[] seatClassType;			// to hold type of seat booked
	
	private int numOfBookedSeat;			// number of booked seats
	
	private Scanner in = new Scanner(System.in);// just now, for using command line interface, 
	
	// this constructor will be used to log in to system.
	public Customer(String userName, String password)
	{
		this.userName = userName;
		this.password = password;
	}
	
	
	// this constructor will be used to add new coustomer to database.
	public Customer()
	{
		setCustomerDetails();// will ask for customer details from user.
	}
	
	
	// set customer details independtly, i could use GUI or CLI(command line interface).
	private void setCustName()
	{
		/* using the beauty of OOP, i can either get last , first name from CLI OR GUI.
		   at the end i will assign a value to custName
		*/
		System.out.println("\n");
	 	System.out.print("\t Please Enter you paticularies:-\n");
	 	System.out.print("\t First Name-> ");
	 	custName = in.nextLine();
	 	
	 	System.out.print("\t Last Name-> ");
	 	custLastName = in.nextLine();
	}
	
	// address, 
	private void setCustAddress()
	{
		System.out.print("\t Address-> ");
	 	custAddress = in.nextLine();
	}
	
	// telephone number, id number(passport no)
	private void setCustId_TelPhoneNo()
	{
		//custId;
	    //custTelphoneNum;
	 	
	 	System.out.print("\t Passport no-> ");
	 	custId = in.nextLine();
	 	
	 	System.out.print("\t Telephone no-> " );
	 	custTelphoneNum = in.nextLine();
	}
	
	// user name, and password.it needs to access the database to maker sure no two identical user name exists.
	private void setCustLogIn()
	{
	 	System.out.print("\t User Name -> " );
	 	userName = in.nextLine();
	 	
	 	System.out.print("\t Password ->");
	 	password = in.nextLine();
	 		
	}
	
	
	// *******************************************************************************************************
	// set customer details
	//
	public void setCustomerDetails()
	{
	 	short choice = 0;
	 	
	 	try
	 	{
	 		while ( choice != 1 )
	 		{
		 		setCustName();
		 		setCustAddress();
		 		setCustId_TelPhoneNo();
		 		setCustLogIn();
		 	
		 		System.out.print("\t Press 1 for confirm , 2 to discard, 3 to exit -> ");
	 	    	choice = (short) in.nextInt();
	 	    
	 			if ( choice == 2 )
	 				return;// user stop entering data
 			}	// end of while loop
		}
		catch(InputMismatchException ex )
		{
			System.out.println("\t Invaild Input, Programm terminated!!!");
			System.exit(1);
	    }
	}
	
	// to delete record or reservation.
	
	
	
	// ***********************************************************************************************
	// booking a seat.
	// customer allow to choose btween 
	// business class or First class
	public void bookSeat( )
	{
		/* search empty space , if there is empty seat then booked , otherwise , ask if the customer
		 * accept to take the other class type.
		*/
		 
		short counter = 0;
		int[] seatBooked = new int[20];
		
		String[] classType = {"First", "Business"};
		
		while ( true )
		{
			System.out.println("\n\n\n");
			
			System.out.println("\t**************************\n");
			System.out.println("\t**************************\n");
			System.out.println("\t******* Seat Type ******\n");
			System.out.println("\t**************************\n");
			System.out.println("\t**************************\n");
			
			System.out.print("\n\t Please choose class Type:-\n"
							 + "\t1. First class.\n"
							 + "\t2. Business class\n"
							 + "\t3. exit\n"
							 + "\ttEnter your choice->");
			 
	        short choice =  (short) ( in.nextInt());// n -1, wher 0 == classtype "first", 1 = classtype "Business"
	        
	         if ( !(choice > 0 && choice < 4) )
	         {
	            System.out.println( "\t Unexpected input, program terminted!!!") ;
	            System.exit(1); 
             }
	        
	        if ( choice == 3 )
	        {
		        displayBookedSeat(seatBooked,counter);
	        	return; 
        	}
	      
	        	
	        choice--;
	        Seat seat = new Seat();// a seat to book
	        short index = seat.getEmptySeat( classType[choice] );//get index of free desired seat
	        
	        
	        if ( index != -1)//there is empty space
	        {
		        Seat.updateDatabase(index, seat.getIsAvailable());// booked it, no one else can book it.
		        Reservation.insertToDatabase(index,custId);       // customer has made a new reservation, so record it.
		        System.out.println("\n\t Thank you, your booking is sccessful");
		        seatBooked[counter] = index;
		        counter++;
		    }
		    else
		    {
			    // if there is no empty seat, report it to user and ask him to choose the other seat type.
			    System.out.print("\nSorry, there is no any empty " + classType[choice] + " seat left\n"
			                       + "\t Please try to book " 
			                       + (( (choice) == 0 ) ? classType[1]: classType[0])
			                       + " class\n" );
			}    
	    } //end of while loop
	    
	}//end of function.
	
	
	
	//******************************************************************************************************
	// resvNum   : is the resveration number 
	// it will return the index of reservation on arrary custReservation.
	// 
	
	short getIndexOfResv(short resvNum)
	{
		for(int i = 0; i < numOfBookedSeat; i++)
			if ( custReservation[i].getResvNum() == resvNum )
				return (short)i;
				
		return -1;//no reservation with this number.
	}
	//*********************************************************************************************************
	
	
	
	//******************************************************************************************************
	// display all reservation made by customer.
	// return which reservation s(he) want to delete or modify.
	
	public short getResvNum()
	{
		
		PreparedStatement state = null;
		ResultSet resultSet = null;
		short choice = -1;
		numOfBookedSeat = 0;
		
		// display all reservation made by the customer
		String query = "SELECT reservation.resvNum,reservation.seatNum, seat.classType from reservation,seat"
						+" WHERE seat.seatNum = reservation.seatNum AND reservation.custId =?";
		try
		{
			state = DatabaseManager.getInstance().getConnection().prepareStatement(query);
			
			state.setString(1,custId);                      
			
	    	resultSet = state.executeQuery();
			
	    	
	    	// get some usefull data, that will be used to ouput purposes.
	    	ResultSetMetaData metaData = resultSet.getMetaData();
			int numOfColumn = metaData.getColumnCount();
			
			System.out.print("\t");
			for ( int i = 1; i <= numOfColumn; i++)//output clomnNames
				System.out.printf("%-8s\t",metaData.getColumnName(i));
			
			System.out.print("\n\n\t");
				
			while( resultSet.next())// outp the result.
			{
				short resvNum = resultSet.getShort(1);
				short seatNum = resultSet.getShort(2);
				String classType = resultSet.getString(3);			
				
				System.out.printf("%-8s\t%-8s\t%-8s\n\t",resvNum,seatNum,classType);
				
			
				seatClassType[numOfBookedSeat] = new String(classType);
				custReservation[numOfBookedSeat]   = new Reservation(resvNum,this.custId,seatNum);
				numOfBookedSeat++;
			}
			
			resultSet.close();// release resources.
			state.close();//release resources.
			
			// promote user to choose which he would to delete.
			System.out.print("\n\t Please enter Resveration num->");
			choice = (short)in.nextInt();
    	}
    	catch (SQLException sqlException)
		{
			System.out.println("SQLException: " + sqlException.getMessage());
		    System.out.println("SQLState: " + sqlException.getSQLState());
			System.out.println("VendorError: " + sqlException.getErrorCode());
			sqlException.printStackTrace();		
		}
		
		return (choice);
	}
	
	
	
	//************************************************************************************
	// it will delete the reservation from database.
	// report to user if there is any problem.
	
	public void deleteRecord( )
	{
		short choice;
		PreparedStatement state = null;
		
		
		
		    System.out.println("\n\n\n");
			System.out.println("\t**************************\n");
			System.out.println("\t**************************\n");
			System.out.println("\t*****Delete Reservation***\n");
			System.out.println("\t**************************\n");
			System.out.println("\t**************************\n");

		try
		{
			//geting index of seatNum
			
			choice = getResvNum();// will display all reservation, and return which reservation to delete.
			short index = getIndexOfResv(choice);// get index of reservation
			
			
			if ( index  != -1 )// valid choice .
			{
				//delete the record from database;
				state = DatabaseManager.getInstance().getConnection().prepareStatement("DELETE FROM reservation WHERE resvNum =? LIMIT 1");
				state.setInt(1,choice);
			
				state.executeUpdate();
			    state.close();//release resource.
			    
			    // free the seat that was associated by the deleted reservation.
			    Seat.updateDatabase(custReservation[index].getSeatNum(),true);
			    System.out.println("\n\t Reservation has been deleted\n");
			    
			}
			else// bad or invalid inpute.
			{
				System.out.println("\n\t NO Resveration has made with no " + choice );
			}
			
			//state.close();//release resources		
		}
		catch (SQLException sqlException)
		{
			System.out.println("SQLException: " + sqlException.getMessage());
		    System.out.println("SQLState: " + sqlException.getSQLState());
			System.out.println("VendorError: " + sqlException.getErrorCode());
			sqlException.printStackTrace();		
		}
	}
	/*********************************************************************************************************/
	
	
	
	////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// to modify any record or reservateion.
	// modification of customer reservation is done automaticlly.When user wants to modify a reservation, the 
	// function will change seat type the other type ,e.c ( "Business to First and vic vers");
	// if the modification can not be done, the function will report it to the user.
	
	public void modifyRecord( )
	{
		short choice;
		PreparedStatement state = null;
		
		System.out.println("\n\n\n");
		System.out.println("\t**************************\n");
		System.out.println("\t**************************\n");
		System.out.println("\t**** Modify Reservation***\n");
		System.out.println("\t**************************\n");
		System.out.println("\t**************************\n");
	
		try
		{
			//geting index of seatNum
			
			choice = getResvNum();// will display all reservation, and return which reservation to update.
			short revsIndx = getIndexOfResv(choice);// get index of reservation.
			
			if ( revsIndx != -1 )// valid choice .
			{
				//update the database, ;
				Seat seat = new Seat();
				
				
				// if current seat type is "Frist " then we will look for avaiable Business class seat.
				// the modification is just allow to change class type and it is done atomaticly.
				//
				
				String temp =  ( ( seatClassType[revsIndx].equals("First") )? "Business": "First" ) ;
				
				short newSeatIndx = seat.getEmptySeat(temp);// find an new empty space where its type is the value 
															// stored on variable temp. 
				
															
				if ( newSeatIndx != -1 )//there is an empty seat
				{
					// update the reservation.
					state = DatabaseManager.getInstance().getConnection().prepareStatement("UPDATE  reservation SET seatNum =? WHERE resvNum =? LIMIT 1");
					state.setShort(1,newSeatIndx);
					state.setShort(2,choice);
					state.executeUpdate();
					state.close();//release resource.
					 
					 
					Seat.updateDatabase(custReservation[revsIndx].getSeatNum(), true);// free the current seat.
					Seat.updateDatabase(newSeatIndx, false);// book the new one.
					
					System.out.println("\n\t Reservation has been modified\n");
			    }
			    else
			    {
				    System.out.println("\t Reservation can not modified, there is no any empty " + temp 
				    					+ "seats.");
			    }
			}
			else// bad or invalid inpute.
			{
				System.out.println("\t NO Resveration has made with no " + choice );
			}
			
			//state.close();		
		}
		catch (SQLException sqlException)
		{
			System.out.println("SQLException: " + sqlException.getMessage());
		    System.out.println("SQLState: " + sqlException.getSQLState());
			System.out.println("VendorError: " + sqlException.getErrorCode());
			sqlException.printStackTrace();		
		}
	}
	//***************************************************************************************************
		
	
	
	
    /////////////////////////////////////////////////////////////////////////////////////////////////////
	//  adding customer details to the database.
	//  
	public void addCustRecord()
	{
	        PreparedStatement sqlStat = null;
		    try 
		    {
		    
		    // query statement
		    //"insert into resume (id, name, content, date_created ) values(?, ?, ?, ?)"
		    String query =  "INSERT INTO customer VALUES(?,?,?,?,?,?)";
		    // now update the database, table customer.
		    
		    //Statement stat = connect.createStatement();
		    sqlStat = DatabaseManager.getInstance().getConnection().prepareStatement(query);
		    
		    sqlStat.setString(1, custId);
		    sqlStat.setString(2, custName);
		    sqlStat.setString(3, custLastName);
		    sqlStat.setString(4, custTelphoneNum);
		    sqlStat.setString(5, userName);
		    sqlStat.setString(6, password);
		    sqlStat.executeUpdate( );
		    
		    sqlStat.close();// close the statement.
	    }
	    catch(SQLException ex)
	    {
		     System.out.println("SQLException:" + ex.getMessage());
		     System.out.println("SQLState: "  + ex.getSQLState());
		     System.out.println("Vendor Error: " + ex.getErrorCode());
	    }
	    finally
	    {
		    try
		    {
			    sqlStat.close();
		    }
		    catch (SQLException ex)
		    {
			    ex.printStackTrace();
			    System.exit(1);
		    }//end of catch
	    }//end of finally block
	}//end of function
	//**********************************************************************************************************
	
	
	
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// to check athurity of the user to log in to system.
	// the system check if userName, and ID do exist on the database.
	// it returns true if userName and Password match with the data on the database
	// otherwise, it return false.
	
	public  Boolean checkAuthority( )
	{
		PreparedStatement statement = null;// initailizing.
		ResultSet resultSet = null;
		
		try
		{
			
			String query = "SELECT * FROM customer WHERE custUserName =? And custPassword =?";
			
			statement = DatabaseManager.getInstance().getConnection().prepareStatement(query);
			//statement = connect.createStatement();// prepare statement before execution.
			
			statement.setString(1, userName);
			statement.setString(2, password);                       
			
		    resultSet = statement.executeQuery( );
		    //System.out.println("WE reached here");
		    
			
			if ( resultSet.next())//
			{
				custId          = resultSet.getString(1);// according to data base schema 
				custName        = resultSet.getString(2);// order of columns are custId,custName, custLastName,custTelNo      
				custLastName    = resultSet.getString(3);// custUesrName, custPassword.   
				//custAddress     = resultSet.getString(3);            
				custTelphoneNum = resultSet.getString(4);
				userName        = resultSet.getString(5);       
				password        = resultSet.getString(6);    
						  
		    }
		    else
		    { 
			    return (new Boolean(false));                                                   
		     }
		}
		catch (SQLException ex)
		{
			System.out.println("SQLException: " + ex.getMessage());
			return (new Boolean(false));		
		}
		//end of finally block
	     
		return (new Boolean(true));
	}//end of function    
	
	
	
	public void reservationMenu()
	{
		int choice;
		boolean flag = true;// to control the while loop
		
		custReservation = new Reservation[20];//customer reservation
		seatClassType = new String[20];
		
		while( flag )
			{
				System.out.println("\n\n\n");
				System.out.println("\t**************************\n");
				System.out.println("\t**************************\n");
				System.out.println("\t******* Reservation ******\n");
				System.out.println("\t**************************\n");
				System.out.println("\t**************************\n");
	    
	    
	    		System.out.println("\t 1. Book a seat\n");
				System.out.println("\t 2. Modify reservation\n");
				System.out.println("\t 3. Delete revseration\n");
				System.out.println("\t 4. Show all Seats\n");
				System.out.println("\t 5. Exit\n");
				System.out.print("\n\t Enter you choice->");
		
		   
        		choice = (short)in.nextInt();
        		
        		  if ( !(choice > 0 && choice < 6) )
	         	  {
	           		 System.out.println( "\t Unexpected input, program terminted!!!") ;
	            	System.exit(1); 
             	  } 
        		
	   			switch (choice)                    
       			{                                  
       				case 1: bookSeat(); break;     
       				case 2: modifyRecord(); break;
       				case 3: deleteRecord(); break;
       				case 4: Seat.showAllSeat(); break;
       				case 5: flag = false; break;                   
       			}//end of switch loop.
       			
    		}// end of while loop.
	}
	
	
	private void displayBookedSeat(int[] seats,int counter)
	{
		System.out.print("\n\tYou have booked " + ( counter  ) + " seats which are:-\n\t");
		for ( int i = 0;i < counter; i++)
		{
			System.out.print(seats[i] + " ");
		}
	}
}//end of class Customer.java
